package com.xk.order.service;

import com.hy.common.dto.CartDTo;
import com.hy.common.enums.ExceptionEnums;
import com.hy.common.exception.XkException;
import com.hy.common.utils.IdWorker;
import com.hy.item.pojo.Sku;
import com.xk.auth.entiy.UserInfo;
import com.xk.order.client.AddressClient;
import com.xk.order.client.GoodsClient;
import com.xk.order.dto.AddressDTO;
import com.xk.order.dto.OrderDTo;
import com.xk.order.enums.OrderStatusEnum;
import com.xk.order.interceptors.OrderInterceptor;
import com.xk.order.mapper.OrderDetailMapper;
import com.xk.order.mapper.OrderMapper;
import com.xk.order.mapper.OrderStatusMapper;
import com.xk.order.pojo.Order;
import com.xk.order.pojo.OrderDetail;
import com.xk.order.pojo.OrderStatus;
import com.xk.order.utils.PayHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class OrderService {

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderDetailMapper detailMapper;
    @Autowired
    private OrderStatusMapper statusMapper;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private GoodsClient goodsClient;
    @Autowired
    private PayHelper payHelper;

    @Transactional
    public Long createOrder(OrderDTo orderDTo) {

        //1新增订单
        Order order = new Order();
        //1.1订单编号，基本信息
        long orderId = idWorker.nextId();
        order.setOrderId(orderId);
        order.setCreateTime(new Date());
        order.setPaymentType(orderDTo.getPaymentType());

        //1.2用户信息
        UserInfo user = OrderInterceptor.getUser();
        order.setUserId(user.getId());
        order.setBuyerNick(user.getUsername());//用户昵称
        order.setBuyerRate(false);//是否评价
        //1.3收货地址，获收货人信息。然后根据orderDTo中的收货人地址id到数据库中查相关信息
        AddressDTO addr = AddressClient.findById(orderDTo.getAddressId());
        order.setReceiver(addr.getName());//收货人
        order.setReceiverAddress(addr.getAddress());//收货人地址
        order.setReceiverCity(addr.getCity());//收货人城市
        order.setReceiverDistrict(addr.getDistrict());//区
        order.setReceiverMobile(addr.getPhone());//手机号
        order.setReceiverState(addr.getState());//省
        order.setReceiverZip(addr.getZipCode());//邮编
        //1.4总金额
        //CartDTo转换成一个map,key是sku的id，值是对应商品的购买的数量num
        Map<Long, Integer> numMap = orderDTo.getCarts().stream().collect(Collectors.toMap(CartDTo::getSkuId, CartDTo::getNum));
        //获所有sku的id
        Set<Long> ids = numMap.keySet();
        //通过id查询得到sku//将set转换成list
        List<Sku> skus = goodsClient.querySkuByIds(new ArrayList<>(ids));
        long totalPay=0L;
        List<OrderDetail> details = new ArrayList<>();
        //根据id查询sku
        for (Sku sku:skus){

            //计算总价
            totalPay+=sku.getPrice() * numMap.get(sku.getId());
            //封装orderDetail
            OrderDetail detail = new OrderDetail();
            detail.setImage(StringUtils.substringBefore(sku.getImages(),"."));
            detail.setNum(numMap.get(sku.getId()));
            detail.setOrderId(orderId);
            detail.setOwnSpec(sku.getOwnSpec());
            detail.setSkuId(sku.getId());
            detail.setTitle(sku.getTitle());
            detail.setPrice(sku.getPrice());
            details.add(detail);
        }
        order.setTotalPay(totalPay);
        order.setActualPay(totalPay + order.getPostFee() - 0);//实付=总金+邮费-优惠
        //1.5 将order写入数据库,insertSelective是有选择性的新增
        orderMapper.insertSelective(order);

        //2新增订单详情
        int count = detailMapper.insertList(details);
        if (count<=0){
            log.error("======创建订单失败=======");
            throw new XkException(ExceptionEnums.CREATE_ORDER_ERROR);
        }
        //3新增订单状态
        OrderStatus orderStatus = new OrderStatus();
        orderStatus.setCreateTime(new Date());
        orderStatus.setOrderId(orderId);
        orderStatus.setStatus(OrderStatusEnum.UN_PAY.value());
        count=statusMapper.insertSelective(orderStatus);
        if (count!=1){
            log.error("======创建订单失败=======");
            throw new XkException(ExceptionEnums.CREATE_ORDER_ERROR);
        }
        //4减库存.库存在商品微服务中
        List<CartDTo> cartDTos=orderDTo.getCarts();
        goodsClient.decreaseStock(cartDTos);

        return orderId;
    }

    /**
     * 通过订单id查询订单
     * @param id
     * @return
     */
    public Order queryOrderById(Long id) {
        //查询订单
        Order order = orderMapper.selectByPrimaryKey(id);
        if (order==null){
            throw new XkException(ExceptionEnums.ORDER_NOT_FOND);
        }

        //查询订单详情
        OrderDetail detail = new OrderDetail();
        detail.setOrderId(id);
        List<OrderDetail> details = detailMapper.select(detail);
        order.setOrderDetails(details);//将详情添加到订单中
        if (CollectionUtils.isEmpty(details)){
            throw new XkException(ExceptionEnums.ORDER_DETAIL_NOT_FOND);
        }

        //查询订单状态
        OrderStatus orderStatus = statusMapper.selectByPrimaryKey(id);
        order.setOrderStatus(orderStatus);
        if (orderStatus==null){
            throw new XkException(ExceptionEnums.ORDER_STATUS_NOT_FOND);
        }

        return  order;

    }

    /**
     * 生成二维码的支付链接
     * @param orderId
     * @return
     */
    public String createPayUrl(Long orderId) {
        //查询订单
        Order order = queryOrderById(orderId);
        //第一个参数是订单id,第二个参数是总金额，第三个参数是商品描述
        /*Long actualPay = order.getActualPay();//支付金额*/
        Long actualPay=1L;
        OrderDetail detail = order.getOrderDetails().get(0);
        String title = detail.getTitle();
        String payUrl = payHelper.createOrder(orderId, actualPay, title);
        return payUrl;
    }
}
